﻿using LightCAD.Core;
using LightCAD.MathLib;
using LightCAD.Runtime;
using LightCAD.Three;
using netDxf.Tables;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Tmds.DBus;
using static LightCAD.Runtime.Constants;
using Constants = LightCAD.Runtime.Constants;

namespace LightCAD.Drawing
{

    [Flags]
    public enum ViewportStatus
    {
        /// <summary>
        /// 无 没有任何其他事务
        /// </summary>
        None = 0,
        /// <summary>
        /// 正在执行某一个action 工作过程中
        /// </summary>
        InAction = 1,
        /// <summary>
        /// 框选
        /// </summary>
        RectSelect = 2,
        /// <summary>
        /// 右键拖拽平移 整个视口对象
        /// </summary>
        RightButtonPan = 4,
        /// <summary>
        /// 拖拽选中对象
        /// </summary>
        DragSelection = 8,
        /// <summary>
        /// 拖拽控制点对象
        /// </summary>
        DragGrip = 16,
        /// <summary>
        /// 粘贴内容的对象
        /// </summary>
        Pasting = 32,
        /// <summary>
        /// 右键菜单对象
        /// </summary>
        ContextMenu = 64,
        /// <summary>
        /// 正在输入命令中
        /// </summary>
        CmdTextInInput = 128
    }

    /// <summary>
    /// 视口的运行管理类，调度各类活动及处理无活动状态
    /// </summary>
    public class ViewportRuntime
    {
        public IViewportControl Control { get; set; }
        public DisplayType DisplayType { get; set; }
        public ElementAction ActiveAction { get; set; }
        public ViewportStatus Status { get; set; }

        private ViewportStatus storeStatus;

        public string Transparency { get; set; } = ValueFrom.ByLayer;

        public string Color { get; set; } = ValueFrom.ByLayer;

        internal DocumentRuntime docRt;
        public SnapRuntime SnapRt { get; set; }

        public bool IsRefEditing { get; set; }
        public RefEditingObject RefEditingObject { get; set; }
        public SectionEditingObject SectionEditingObject { get; set; }
        public Matrix3 ScrToDcs;
        public Matrix3 DcsToScr;

        public Matrix3 DcsToWcs;
        public Matrix3 WcsToDcs;

        public Matrix3 WcsToScr;
        public Matrix3 ScrToWcs;

        public Matrix3 UcsToWcs;
        public Matrix3 WcsToUcs;

        public Matrix3 UcsToScr;
        public Matrix3 ScrToUcs;
        private ICreateDrawer createDrawer;
        private ITransformDrawer transformDrawer;
        /// <summary>
        /// 指针按下坐标
        /// </summary>
        public SKPoint PointerPressedPosition { get; set; }
        /// <summary>
        /// 指针移动坐标
        /// </summary>
        public SKPoint PointerMovedPosition { get; set; }
        /// <summary>
        /// 指针释放坐标
        /// </summary>
        public SKPoint PointerReleasedPosition { get; set; }
        /// <summary>
        /// 滚轮触发的指针坐标
        /// </summary>
        public SKPoint PointerWheelPosition { get; set; }


        public LcViewport Viewport { get; private set; }

        public Vector2 PanCenter { get; internal set; }

        public ViewportRenderer Renderer { get; private set; }

        public LcCursorType CursorType { get; set; } = LcCursorType.SelectElement;
        public CursorAddonType CursorAddon { get; set; } = CursorAddonType.None;

        /// <summary>
        /// 当前活动的元素集，用于各类元素操作
        /// </summary>
        public ElementSpace ActiveElementSet { get; set; }
        /// <summary>
        /// 当前非活动的元素集，一般情况为空，在位编辑时，为ModelSpace
        /// </summary>
        public ElementSpace DeactiveElementSet { get; set; }

        public ICreateDrawer CreateDrawer { get => createDrawer; set => createDrawer = value; }
        public ITransformDrawer TransformDrawer { get => transformDrawer; set => transformDrawer = value; }
        public bool IsCreateDrawing { get; set; }
        public bool IsTrimAction { get; set; }
        public List<Box2> TrimBox2s { get; set; }
        public List<LcElement> TrimElements { get; set; }
        public bool IsTransformDrawing { get; set; }
        public IPopupObject HoveredTip { get; set; }

        public CommandCenter CommandCenter { get; private set; }
        public ICommandControl CommandCtrl { get; private set; }
        public IDocumentEditor DocEditor { get; private set; }
        
        public Vector2 PrePoint { get; set; }
        public ViewportRuntime(IDocumentEditor docEditor, LcViewport viewport, IViewportControl control)
        {
            this.DocEditor = docEditor;
            this.docRt = docEditor.DocRt;
            this.docRt.Action.SelectsChanged += Action_SelectsChanged;
            this.docRt.PropertyUIChanged += DocRt_PropertyUIChanged;
            this.Viewport = viewport;
            this.Control = control;           
            this.Renderer = new ViewportRenderer(docRt, this);
            // this.Control.DetachEvents(this.OnMouseEvent, this.OnKeyDown,this.OnKeyUp, this.OnSizeChanged, this.OnSkRender);
            this.Control.AttachEvents(this.OnMouseEvent, this.OnKeyDown, this.OnKeyUp, this.OnSizeChanged, this.OnSkRender);

            this.ActiveElementSet = this.docRt.Document.ModelSpace;
            this.DeactiveElementSet = null;

            this.CommandCenter = this.DocEditor.CommandCenter;
            this.CommandCtrl = this.CommandCenter.Commander;

        }

        private void DocRt_PropertyUIChanged(List<LcElement> eles)
        {
            foreach (var ele in eles)
            {
                ele.ResetBoundingBox();
                DrawDraggingGrip = null;
                ClearElementGrips(new List<LcElement> { ele });
                ResetElementGrips(new List<LcElement> { ele });
            }
            this.docRt.UIPropertyChange();
        }

        private void Action_SelectsChanged(IDocumentEditor sender, SelectedEventArgs args)
        {
            if (args.Selected)
            {
                this.ResetElementGrips(args.Elements);
            }
            else
            {
                this.ClearElementGrips(args.Elements);
            }


        }
   

    
        public void GetTrimRect()
        {
            Vector2 pressPoint2 = this.ConvertScrToWcs(this.PointerReleasedPosition.ToVector2d());
            Box2 box = new Box2();
            if (this.CheckStatus(ViewportStatus.RectSelect))
            {
                Vector2 pressPoint1 = this.ConvertScrToWcs(this.PointerPressedPosition.ToVector2d());
                double mix = pressPoint1.X < pressPoint2.X ? pressPoint1.X : pressPoint2.X;
                double max = pressPoint1.X > pressPoint2.X ? pressPoint1.X : pressPoint2.X;
                double miY = pressPoint1.Y < pressPoint2.Y ? pressPoint1.Y : pressPoint2.Y;
                double maY = pressPoint1.Y > pressPoint2.Y ? pressPoint1.Y : pressPoint2.Y;
                box = new Box2(mix, miY, max, maY);      
            }
            if (!this.CheckStatus(ViewportStatus.RectSelect))
            {
                //点选盒子的尺寸
                double selectSize = this.ConvertScrToWcs(Constants.SelectBoxSize);
                box = new Box2(new Vector2(pressPoint2.X - selectSize, pressPoint2.Y - selectSize), selectSize * 2, selectSize * 2);
            }
            if (TrimBox2s == null)
            {
                TrimBox2s = new List<Box2>();
            }
            TrimBox2s.Add(box);
        }

        public bool CheckStatus(ViewportStatus status)
        {
            if (status == ViewportStatus.None)
                return status == this.Status;
            else
                return (status & this.Status) == status;
        }
        public void SetStatus(ViewportStatus status, bool isClear = true)
        {
            if (isClear)
                this.Status = status;
            else
                this.Status |= status;
        }
        public void RemoveStatus(ViewportStatus status)
        {
            this.Status &= ~status;
        }
        public void ClearStatus()
        {
            this.Status = ViewportStatus.None;
        }
        public void OnSizeChanged(Bounds bounds)
        {
            this.Viewport.Width = bounds.Width;
            this.Viewport.Height = bounds.Height;
            this.Control.ForceRefresh = true;

            ResetCoordMatrix();

            Renderer.ScrScope = bounds.ToSKRect();
            Renderer.WorldScope.Min.Set(-Renderer.OriginX, -Renderer.OriginY);
            Renderer.WorldScope.Max.Set(
                -Renderer.OriginX + Renderer.ScrScope.Width / Renderer.Zoom,
                -Renderer.OriginY + Renderer.ScrScope.Height / Renderer.Zoom);
        }
        private bool isInitCoord;
        public void ResetCoordMatrix()
        {
            var vp = this.Viewport;
            if (!isInitCoord)
            {
                vp.Scale = 0.05;
                isInitCoord = true;
            }

            //从屏幕到中心设备坐标系 相当于平移加镜像
            this.DcsToScr = Matrix3.GetTranslate(vp.Width / 2, vp.Height / 2) * Matrix3.GetScale(1, -1);
            this.ScrToDcs = this.DcsToScr.Clone().Invert();

            //从设备坐标转换到世界坐标系
            this.WcsToDcs = Matrix3.GetTranslate(vp.Center.X, vp.Center.Y) * Matrix3.GetScale(vp.Scale);
            this.DcsToWcs = this.WcsToDcs.Clone().Invert();

            //世界坐标系直接到屏幕
            this.WcsToScr = DcsToScr * this.WcsToDcs;
            this.ScrToWcs = this.WcsToScr.Clone().Invert();


            //两次分别的转换等同于一次转换
            //DcsToWcs->ScrToDcs == ScrToWcs

            if (this.Viewport.Ucs.IsIdentity())
            {
                this.WcsToUcs = Matrix3.Identity;
                this.UcsToWcs = Matrix3.Identity;
                this.UcsToScr = WcsToScr;
                this.ScrToUcs = ScrToWcs;
            }
            else
            {
                //用户坐标系到世界坐标系
                this.UcsToWcs = this.Viewport.Ucs.Matrix;
                this.WcsToUcs = this.UcsToWcs.Clone().Invert();

                //用户坐标系直接到屏幕
                this.UcsToScr = this.WcsToScr * this.UcsToWcs;
                this.ScrToUcs = this.UcsToScr.Clone().Invert();

                if (this.Viewport.Ucs.IsPlan)
                {
                    //用户坐标系放平，等同于对所有坐标系进行反向旋转
                    var angle = this.Viewport.Ucs.XAxis.Angle();
                    var rtmat = Matrix3.RotateInRadian(angle, this.Viewport.Ucs.Origin);

                    this.DcsToScr = Matrix3.Multiply(rtmat, this.DcsToScr);
                    this.ScrToDcs = this.DcsToScr.Clone().Invert();

                    this.WcsToScr = Matrix3.Multiply(rtmat, this.WcsToScr);
                    this.ScrToWcs = this.WcsToScr.Clone().Invert();

                    this.UcsToScr = Matrix3.Multiply(rtmat, this.UcsToScr);
                    this.ScrToUcs = this.UcsToScr.Clone().Invert();
                }
            }
        }
        internal virtual void OnMouseEvent(string type, MouseEventRuntime e)
        {
            //如果有Action执行，则由相关Action接管处理
            if (ActiveAction != null) return;

            if (type == "Down") OnMouseDown(e);
            else if (type == "Move") OnMouseMove(e);
            else if (type == "Up") OnMouseUp(e);
            else if (type == "Wheel") OnMouseWheel(e);
            else if (type == "HoverStart") OnMouseHoverStart(e);
            else if (type == "HoverEnd") OnMouseHoverEnd(e);

        }
        public bool IsUcsOpened
        {
            get { return !this.Viewport.Ucs.IsIdentity(); }
        }
        public bool IsUcsPlan
        {
            get { return this.Viewport.Ucs.IsPlan; }
        }

        #region Events


        private void OnMouseDown(MouseEventRuntime e)
        {
            this.PointerPressedPosition = e.Location;
            //TODO:对于右键平移的INaction状态也需要处理
            //if (CheckStatus(ViewportStatus.InAction))
            //{
            //    return;
            //}
            if (CheckStatus(ViewportStatus.None))
            {
                //如果没有前序状态，进行如下判断
                if (e.Button == LcMouseButtons.Left)
                {
                    //控制柄选中检测，如果选中进入拖拽控制点模式
                    var grip = this.HitSelectGrip();
                    if (grip != null)
                    {
                        SetStatus(ViewportStatus.DragGrip);
                        this.SnapRt = new SnapRuntime(this);
                        PrePoint = this.ConvertScrToWcs(e.Location.ToVector2d());
                        goto Label_End;
                    }


                    //选中/不选中 元素检测，Click为选中，Shift+Click为不选中
                    LcElement hitEle = null;

                    if (e.KeyModifiers == LcKeyModifiers.Shift)
                    {
                        hitEle = this.HitUnselect();
                    }
                    else
                    {
                        //选中元素后，如果重复选中，进入选中拖拽模式
                        bool isFirstSelected = false;
                        hitEle = this.HitSelect(ref isFirstSelected);
                        if (hitEle != null && !isFirstSelected)
                        {
                            OnMouseHoverEnd(e);
                            if (this.docRt.Document.Layers.Where(x => x.Name == hitEle.Layer).First().IsLocked)
                                return;
                            SetStatus(ViewportStatus.DragSelection);
                            this.docRt.Action.DragSelectionX = 0;
                            this.docRt.Action.DragSelectionY = 0;
                            return;
                        }
                    }
                    //如果没有选中元素，则进入矩形框选模式
                    if (hitEle == null)
                    {
                        SetStatus(ViewportStatus.RectSelect);
                        CursorType = LcCursorType.None;
                    }
                }
                else if (e.Button == LcMouseButtons.Right)
                {
                    //点击右键进入右键平移模式，此模式需要保持当前状态，以确保平移后回到当前状态
                    this.storeStatus = this.Status;//将当前的状态进行保存
                    SetStatus(ViewportStatus.RightButtonPan);
                    this.PanCenter = this.Viewport.Center;
                    this.PointerMovedPosition = e.Location;//清除前序Moved坐标
                }

            }
            else if (CheckStatus(ViewportStatus.CmdTextInInput))
            {
                return;
            }
            else if (CheckStatus(ViewportStatus.DragSelection))
            {
                ClearStatus();
                this.EndDragSelection(e.KeyModifiers == LcKeyModifiers.Control);
            }
            else if (CheckStatus(ViewportStatus.Pasting))
            {
                this.PasteDone();
                ClearStatus();
            }
            else if (CheckStatus(ViewportStatus.DragGrip))
            {
                //TODO BeginAction代码放在这里不合适
                DocumentManager.CurrentRecorder.BeginAction("DragGrip");
                this.DraggingGripEnd();
                this.SnapRt = null;
                //拖拽控制点结束
                ClearStatus();
                DocumentManager.CurrentRecorder.EndAction();
            }

        Label_End:
            return;
        }

        //返回辅助线颜色值
        public uint GetAuxColorValue()
        {
            uint colorValue;
            this.Color = this.docRt.Document.Color;
            string layer = this.docRt.Document.Layers.Where(x => x.IsStatus == true).FirstOrDefault().Name;
            LcLayer lcLayer = this.docRt.Document.Layers.GetByName(layer);
            if (this.Color == ValueFrom.ByLayer)
            {
                colorValue = lcLayer.Color;
            }
            else if (this.Color == ValueFrom.ByBlock)
            {
                colorValue = 0xFF000000;
            }
            else
            {
                string PATTERN = @"([^A-Fa-f0-9]|\s+?)+";
                if (uint.TryParse(this.Color, out uint c))
                {
                    colorValue = c;
                }
                else if (Regex.IsMatch(this.Color, PATTERN))
                {
                    var html = ColorTranslator.FromHtml(this.Color);
                    colorValue = (uint)html.ToArgb();
                }
                else
                {
                    colorValue = 0xFF000000;
                }
            }
            uint alpha = 200;
            string alphaValue = alpha.ToString("X");
            string color = colorValue.ToString("X");
            string result = alphaValue + color.Substring(2);
            colorValue = uint.Parse(result, System.Globalization.NumberStyles.HexNumber);
            return colorValue;
        }
        //#region Hover

        //private SKPoint preHover;
        //private bool isPointerHovering;
        //private System.Timers.Timer hoverTimer;
        //private void HoverTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        //{
        //    hoverTimer.Stop();
        //    this.isPointerHovering = true;
        //    HoverEventStart();
        //}
        private void OnMouseHoverStart(MouseEventRuntime e)
        {
            if (CheckStatus(ViewportStatus.None))
            {
                this.HoverSelect();
            }
            if (this.SnapRt == null) return;
            else
            {
                var mp = this.ConvertScrToWcs(e.Location.ToVector2d());
                this.SnapRt.MouseHover(mp);
            }
        }
        private void OnMouseHoverEnd(MouseEventRuntime e)
        {
            if (CheckStatus(ViewportStatus.None))
            {
                this.HoverUnselect();
            }
        }

        //#endregion

        private void OnMouseMove(MouseEventRuntime e)   //鼠标按住移动事件
        {
            this.PointerMovedPosition = e.Location;
            Vector2 Location = this.ConvertScrToWcs(this.PointerMovedPosition.ToVector2d());
            if (this.SnapRt?.Current != null)//判断有没有捕捉到点
            {
                Location = this.SnapRt.Current.SnapPoint;
            }
            DrawingEditRuntime drawingEditRuntime = this.DocEditor as DrawingEditRuntime;
            string x = Location.X.ToString("f4");
            string y = Location.Y.ToString("f4");
            drawingEditRuntime.Control.SetLocation(x + "，" + y + "，" + "0.0000");//调用接口
            //drawingEditRuntime.Control.SetLocation()
            //TODO: 对于右键平移的INaction状态也需要处理
            if (CheckStatus(ViewportStatus.InAction))
            {
                return;
            }
            if (CheckStatus(ViewportStatus.Pasting))
            {
                return;
            }

            if (CheckStatus(ViewportStatus.None))
            {

                ////模拟处理悬停事件，停在某点一段时间触发事件，移动光标悬停结束，等待下一次悬停事件
                ////需要位置发生改变才停止Hover事件，因为ToolTip的显示，会导致Move事件的重复触发
                //if (this.isPointerHovering && preHover != this.PointerMovedPosition)
                //{
                //    this.isPointerHovering = false;
                //    HoverEventEnd();
                //}
                //hoverTimer.Stop();
                //hoverTimer.Start();

            }

            if (CheckStatus(ViewportStatus.CmdTextInInput))
            {
                return;
            }
            if (CheckStatus(ViewportStatus.RightButtonPan))
            {
                this.PanViewScope();
            }

            if (CheckStatus(ViewportStatus.RectSelect)
                || CheckStatus(ViewportStatus.RightButtonPan)
                || CheckStatus(ViewportStatus.Pasting))
            {
                return;
            }

            if (CheckStatus(ViewportStatus.DragGrip))
            {

                this.DraggingGrip();

            }
            else if (CheckStatus(ViewportStatus.DragSelection))
            {
                if (e.KeyModifiers == LcKeyModifiers.Control)
                    this.CursorAddon = CursorAddonType.Plus;
                else
                    this.CursorAddon = CursorAddonType.None;

                this.DragSelects();
            }


            //VPort.ShowFloatBlock(this);

            //lblDrawCount.Content = VPort.DrawCounter + "/" + doc.ModelSpace.Elements.Count;

        }

        private void OnMouseUp(MouseEventRuntime e)     //鼠标松手触发的事件
        {
            this.PointerReleasedPosition = e.Location;
            //TODO:对于右键平移的INaction状态也需要处理
            if (this.IsTrimAction)
            {
                GetTrimRect();
            }
            if (CheckStatus(ViewportStatus.RectSelect))
            {
                ClearStatus();
                CursorType = LcCursorType.SelectElement;
                this.RectSelects();
            }
            if (CheckStatus(ViewportStatus.CmdTextInInput))
            {
                return;
            }
            if (CheckStatus(ViewportStatus.RightButtonPan))
            {
                SetStatus(this.storeStatus);//平移结束后立即恢复前一个状态
                if (PopupContextMenu())
                {
                    SetStatus(ViewportStatus.ContextMenu);

                }
            }

            if (CheckStatus(ViewportStatus.DragSelection))
            {
                ClearStatus();
                this.EndDragSelection(e.KeyModifiers == LcKeyModifiers.Control);
            }

        }

        private void OnMouseWheel(MouseEventRuntime e)
        {
            if (!CheckStatus(ViewportStatus.DragSelection))
            {
                PointerWheelPosition = e.Location;
                if (e.DeltaY < 0)
                {
                    if (this.Viewport.Scale < 0.000001)
                    {
                        return;
                    }

                }
                else
                {
                    if (this.Viewport.Scale > 50000)
                    {
                        return;
                    }

                }
                this.ZoomWheel(e.DeltaY);
                //VPort.Zoom = Math.Round(VPort.Zoom, 12);
                Control.ShowInfo("zoom", this.Viewport.Scale);
            }
        }

        internal virtual void OnKeyDown(KeyEventRuntime e)
        {
            if (e.KeyCode == 17)//Ctrl
            {
                if (CheckStatus(ViewportStatus.DragSelection))
                {
                    if (e.KeyModifiers == LcKeyModifiers.Control)
                        this.CursorAddon = CursorAddonType.Plus;
                    else
                        this.CursorAddon = CursorAddonType.None;
                }
            }
            else if (e.KeyCode == 27)//ESC
            {
                this.CancelAll();
            }
           
            if (!CheckStatus(ViewportStatus.None)) return;

            if (e.KeyModifiers == LcKeyModifiers.Control)
            {
                if (e.KeyCode == 'Z')//Ctrl-Z undo
                {
                    CommandCenter.Execute("UNDO");
                }
                else if (e.KeyCode == 'Y')//Ctrl-Y redo
                {
                    CommandCenter.Execute("REDO");
                }
                else if (e.KeyCode == 'C')//Ctrl-C copy
                {
                    CommandCenter.Execute("COPY");
                }
                else if (e.KeyCode == 'X')//Ctrl-Y cut
                {
                    CommandCenter.Execute("CUT");
                }
                else if (e.KeyCode == 'V')//Ctrl-V paste
                {
                    CommandCenter.Execute("PASTE");
                    SetStatus(ViewportStatus.Pasting);
                }
                else if (e.KeyCode == 'S')//Ctrl-S save
                {
                    CommandCenter.Execute("SAVE");
                }
                else if (e.KeyCode == 'A')//Ctrl-A select all
                {
                    CommandCenter.Execute("SELECTALL");
                }
            }
            else if (e.KeyCode == 46)//Delete
            {
                CommandCenter.Execute("ERASE");
            }

            //处理在位输入及Esc/Copy，Cut/Paste将启动相应Action
        }

        internal virtual void OnKeyUp(KeyEventRuntime e)
        {
            if (e.KeyCode == 17)//Ctrl
            {
                if (CheckStatus(ViewportStatus.DragSelection))
                {
                    if (e.KeyModifiers == LcKeyModifiers.Control)
                        this.CursorAddon = CursorAddonType.Plus;
                    else
                        this.CursorAddon = CursorAddonType.None;
                }
            }

            if (!CheckStatus(ViewportStatus.None)) return;

        }

        internal virtual void OnSkRender(SKSurface surface)
        {

            if (!Control.ForceRefresh && !Control.IsActive) return;
            Control.ForceRefresh = false;

            var canvas = surface.Canvas;

            this.Renderer.Clear(canvas);
            //this.Renderer.DrawGrid(canvas);
            this.Renderer.DrawOriginAxis(canvas);


            if (CheckStatus(ViewportStatus.RectSelect))
            {
                this.Renderer.DrawSelectRect(canvas, this.PointerPressedPosition, this.PointerMovedPosition);
            }

            //处于捕捉状态
            if (this.SnapRt != null)
            {
                if (this.SnapRt.RefPoints.Count > 0)
                {
                    this.Renderer.DrawSnapRefPoints(canvas);
                }
                if (this.SnapRt.RefCurves.Count > 0)
                {
                    this.Renderer.DrawSnapRefCurves(canvas);
                }
                if (this.SnapRt.Current != null)
                {
                    this.Renderer.DrawSnapPoint(canvas);
                }

            }


            if (!Viewport.Ucs.IsIdentity())
            {
                this.Renderer.DrawUcsIcon(canvas);
            }

            this.Renderer.DrawElements(canvas);   //绘制完的渲染，是这句话触发的
            //Debug.Print("Document: "+this.docRt.Document.FilePath);

            if (this.docRt.Action.SelectedElements.Count > 0 && Control.IsActive)
            {
                this.Renderer.DrawElementGrips(canvas);  //拖拽元素的渲染
            }

            if (this.IsCreateDrawing)  //是否在创建过程中渲染
            {
                this.createDrawer.DrawTemp(canvas);
                this.createDrawer.DrawAuxLines(canvas);
            }
            if (this.IsTransformDrawing)
            {
                this.transformDrawer.DrawTrans(canvas);

            }
            if (CheckStatus(ViewportStatus.DragGrip))   //当前拖拽过程中  选点
            {
                this.Renderer.DrawDragGrip(canvas);
            }
            if (CheckStatus(ViewportStatus.DragSelection))   //拖拽选中对象  选线
            {
                this.Renderer.DrawDraggingSelection(canvas);
            }

            if (CheckStatus(ViewportStatus.Pasting))   //粘贴过程中的渲染
            {
                this.Renderer.DrawPasteElments(canvas, this.PointerMovedPosition);
            }

            if (Control.IsActive && CursorType != LcCursorType.None)
            {
                //DrawArc使用示范
                {
                    var p = this.ConvertScrToWcs(this.PointerMovedPosition.ToVector2d());
                    var arc2d = new Arc2d
                    {
                        Center = p,
                        StartAngle = Math.PI / 4,
                        EndAngle = Math.PI * 3 / 4,
                        Radius = 100,
                        IsClockwise = false
                    };
                    this.DrawArc(arc2d, Matrix3.Identity, canvas, Constants.defaultPen);
                }
                this.Renderer.DrawCrossCursor(canvas, CursorType, CursorAddon);
            }

        }

        #endregion

        private void HoverSelect()
        {
            var scrp = PointerMovedPosition.ToVector2d();
            var pw = ConvertScrToWcs(scrp);
            var sizew = SelectBoxSize / this.Viewport.Scale;
            var grip = this.HoverSelectGrip(pw, sizew);
            //如果没有悬停控制点，则判断有无悬停元素
            if (grip == null)
            {
                var element = this.docRt.Action.HoverSelectElement(docRt.Document.ModelSpace, pw, sizew);
                if (element != null)
                {
                    HoveredTip = this.Control.GetPopupObject("ElementHover");
                    this.Control.Invoke(() =>
                    {
                        var sp = this.Control.PointToScreen(PointerMovedPosition);
                        HoveredTip.Show((int)sp.X + 4, (int)sp.Y + 4);
                    });
                }
            }
        }
        private void HoverUnselect()
        {
            this.HoverUnselectGrip();
            this.docRt.Action.HoverUnselectElement();
            if (HoveredTip != null)
            {
                HoveredTip.Hide();
            }
        }


        internal void CancelAll()
        {
            this.CommandCtrl.WriteInfo(this.CommandCtrl.GetPrompt() + "*取消*");
            ClearStatus();
            this.CurrentAction = null;
            this.CursorType = LcCursorType.SelectElement;
            this.CursorAddon = CursorAddonType.None;
            CommandCenter.InAction = false;
            CancelCurrentAction();
            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.docRt.Action.SetSelectsToDragging(false);
                this.ClearElementGrips();
                this.docRt.Action.ClearSelects();
            }
        }

        internal void SelectAll()
        {
            this.docRt.Action.SelectElements(this.DocEditor, this.docRt.Document.ModelSpace.Elements.ToList());
        }

        #region Drag
        internal void EndDragSelection(bool isControlPressed) //isControlPressed是判断的按键
        {
            var pre = ConvertScrToWcs(PointerPressedPosition.ToVector2d());
            var cur = ConvertScrToWcs(PointerReleasedPosition.ToVector2d());
            this.docRt.Action.DragSelectionX = cur.X - pre.X;
            this.docRt.Action.DragSelectionY = cur.Y - pre.Y;
            CursorAddon = CursorAddonType.None;
            this.docRt.Action.SetSelectsToDragging(false);
            this.ClearElementGrips();

            if (isControlPressed)
                this.DragCopySelection(this.docRt.Action.DragSelectionX, this.docRt.Action.DragSelectionY);
            else
                this.DragSelection(this.docRt.Action.DragSelectionX, this.docRt.Action.DragSelectionY);
        }
        internal void DragCopySelection(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGCOPY");
            ElementSpace eleSet = this.ActiveElementSet;
            var copyElements = new List<LcElement>();
            var docAction = this.docRt.Action;
            foreach (var element in docAction.SelectedElements)
            {
                var copyEle = element.Clone();
                eleSet.InsertElement(copyEle);
                copyElements.Add(copyEle);
            }
            foreach (var element in copyElements)
            {
                eleSet.MoveElement(element, dragX, dragY);
            }

            docAction.SetSelectsToDragging(false);
            docAction.ClearSelects();
            docAction.SelectElements(this.DocEditor, copyElements);
            this.ResetElementGrips(copyElements);
            DocumentManager.CurrentRecorder.EndAction();

        }
        internal void DragSelection(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGMOVE");
            var docAction = this.docRt.Action;
            foreach (var element in docAction.SelectedElements)
            {
                this.ActiveElementSet.MoveElement(element, dragX, dragY);
            }
            this.ResetElementGrips(docAction.SelectedElements);
            DocumentManager.CurrentRecorder.EndAction();
        }

        internal void DragSelects()
        {
            var pre = ConvertScrToWcs(PointerPressedPosition.ToVector2d());
            var mov = ConvertScrToWcs(PointerMovedPosition.ToVector2d());
            this.docRt.Action.DragSelectionX = mov.X - pre.X;
            this.docRt.Action.DragSelectionY = mov.Y - pre.Y;
        }

        private void DraggingGrip()
        {
            var pos = ConvertScrToWcs(PointerMovedPosition.ToVector2d());
            this.DraggingGrip(pos);
        }
        private void DraggingGripEnd()
        {
            var p = ConvertScrToWcs(PointerPressedPosition.ToVector2d());
            this.DraggingGripEnd(p);
            this.docRt.UIPropertyChange();
        }
        internal void Drag(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGMOVE");
            foreach (var element in this.docRt.Action.SelectedElements)
            {
                (element.Parent as ElementSpace).MoveElement(element, dragX, dragY);
                //this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.MoveElement(element, dragX, dragY);
            }
            this.ResetElementGrips(this.docRt.Action.SelectedElements);
            DocumentManager.CurrentRecorder.EndAction();
        }
        public void DragCopy(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGCOPY");
            var copyElements = new List<LcElement>();
            foreach (var element in this.docRt.Action.SelectedElements)
            {
                var copyEle = element.Clone();
                this.ActiveElementSet.InsertElement(copyEle);
                copyElements.Add(copyEle);
            }
            foreach (var element in copyElements)
            {
                this.ActiveElementSet.MoveElement(element, dragX, dragY);
            }
            this.docRt.Action.SetSelectsToDragging(false);
            this.docRt.Action.ClearSelects();
            this.docRt.Action.SelectElements(null, copyElements);

            //this.Action.ResetElementGrips(copyElements);
            DocumentManager.CurrentRecorder.EndAction();

        }
        #endregion

        #region Select
        public List<LcElement> RectSelects()
        {
            //var fpw = ConvertScrToUcs(PointerPressedPosition.ToVector2d());
            //var spw = ConvertScrToUcs(PointerReleasedPosition.ToVector2d());
            //var selectBox = new Box2d(fpw, spw);
            var fp = PointerPressedPosition.ToVector2d();
            var sp = PointerReleasedPosition.ToVector2d();
            var selectBox = new Box2().SetFromPoints(fp, sp);
            var elements = this.RectSelects(this.docRt.Document.ModelSpace, selectBox, sp.X > fp.X);

            this.docRt.Action.SelectElements(this.DocEditor, elements);
            //只有之前没有选中的元素才再创建夹点
            this.ResetElementGrips(elements.FindAll(e => !e.IsSelected));
            return elements;
        }
        public List<LcElement> RectSelects(ElementSpace container, Box2 selectBox, bool isInclude)
        {
            //TODO:RectSelects放在这里似乎不不合理

            //屏幕矩形，转换为世界坐标系多边形
            var selectPoly = selectBox.ToPolygon(this.ScrToWcs);
            //if (!this.docRt.DrawingEditRt.ActiveViewportRt.Viewport.Ucs.IsIdentity())
            //{
            //    selectPoly = selectPoly.Multiply(this.docRt.DrawingEditRt.ActiveViewportRt.WcsToUcs);
            //}
            var elements = new List<LcElement>();
            for (var i = container.Elements.Count - 1; i >= 0; i--)
            {
                var ele = container.Elements[i];
                ////如果处在在位编辑状态，处于顶层的Ref元素不可选择
                if (this.IsRefEditing && ele == this.RefEditingObject.RefLinks[0])
                {
                    var subSelects = new List<RefChildElement>();
                    var refSeleccted = isInclude ? ele.IncludedByBox(selectPoly, subSelects) : ele.IntersectWithBox(selectPoly, subSelects);
                    if (subSelects.Count > 0)
                    {
                        foreach (var subItem in subSelects)
                        {
                            //选中的子元素要属于指定的引用
                            if (subItem.RefObject == this.RefEditingObject.Target)
                            {
                                var subEle = subItem.Element;
                                elements.Add(subEle);
                            }
                        }
                    }
                    continue;
                }


                var selected = isInclude ? ele.IncludedByBox(selectPoly) : ele.IntersectWithBox(selectPoly);
                if (selected)
                {
                    elements.Add(ele);
                }
            }
            return elements;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <param name="hitPoint"></param>
        /// <param name="selectSize"></param>
        /// <returns>选中的元素，是否是新选中</returns>
        public Tuple<LcElement, bool> HitSelect(ElementSpace container, Vector2 hitPoint, double selectSize)
        {
            var testPoly = new Box2(new Vector2(hitPoint.X - selectSize, hitPoint.Y - selectSize), selectSize * 2, selectSize * 2).ToPolygon();
            for (var i = container.Elements.Count - 1; i >= 0; i--)
            {
                var ele = container.Elements[i];
                var intersected = ele.IntersectWithBox(testPoly);
                if (intersected)
                    return new Tuple<LcElement, bool>(ele, !ele.IsSelected);
            }
            return null;
        }

        public List<LcElement> HitSelect(ElementSpace container, Vector2 hitPoint1, Vector2 hitPoint2)
        {
            var lcElements = new List<LcElement>();  //建立一个集合  将选中的元素放在集合里面
            var testPoly = new Box2(hitPoint1.X, hitPoint1.Y, hitPoint2.X, hitPoint2.Y).ToPolygon();
            for (var i = container.Elements.Count - 1; i >= 0; i--)
            {
                var ele = container.Elements[i];
                var intersected = ele.IntersectWithBox(testPoly); //判断盒子里面是否有没有选中的元素
                if (intersected)
                {
                    if (!ele.IsSelected)
                    {
                        lcElements.Add(ele);
                    }
                }
            }
            return lcElements;
        }

        public ControlGrip HitSelectGrip()
        {
            var pw = ConvertScrToWcs(PointerPressedPosition.ToVector2d());
            var sizew = (SelectBoxSize) / this.Viewport.Scale;
            var grip = this.HitSelectGrip(pw, sizew);
            if (grip == null) return null;

            SetStatus(ViewportStatus.DragGrip);
            return grip;

        }
        public LcElement HitUnselect()
        {
            var pw = this.ConvertScrToWcs(PointerPressedPosition.ToVector2d());
            ///var sizew = (SelectBoxSize) / this.Viewport.Scale;
            var sizew = this.ConvertScrToWcs(SelectBoxSize);
            var element = this.HitUnselect(this.ActiveElementSet, pw, sizew);
            if (element != null) this.ClearElementGrips(new List<LcElement> { element });
            return element;

        }
        public LcElement HitUnselect(ElementSpace container, Vector2 hitPoint, double selectSize)
        {
            for (var i = container.Elements.Count - 1; i >= 0; i--)
            {
                var ele = container.Elements[i];
                var testBox = new Box2(new Vector2(hitPoint.X - selectSize, hitPoint.Y - selectSize), selectSize * 2, selectSize * 2);
                var intersected = ele.IntersectWithBox(testBox.ToPolygon());
                if (intersected)
                {
                    if (ele.IsSelected)
                    {
                        this.docRt.Action.ClearSelects(this.DocEditor, new List<LcElement> { ele });
                        return ele;
                    }
                    return null;
                }
            }
            return null;
        }
        public LcElement HitSelect(ref bool isFirstSelected)
        {
            var pw = this.ConvertScrToWcs(this.PointerPressedPosition.ToVector2d());
            var sizew = Constants.SelectBoxSize / this.Viewport.Scale;
            var result = this.HitSelect(this.ActiveElementSet, pw, sizew);

            if (result == null) return null;
            this.docRt.Action.SelectElements(this.DocEditor, new List<LcElement> { result.Item1 });
            if (result.Item2 == true)//首次选中
            {
                this.ResetElementGrips(new List<LcElement> { result.Item1 });
            }
            isFirstSelected = result.Item2;
            return result.Item1;
        }
        #endregion

        #region Grip Control

        public List<ControlGrip> ElementGrips = new List<ControlGrip>();
        public ControlGrip SelectedGrip;
        public ControlGrip HoveredGrip;

        public void ResetElementGrips(List<LcElement> elements)
        {
            foreach (LcElement element in elements)
            {
                //图层锁定关闭元素夹点
                if (this.docRt.Document.Layers.Where(x => x.Name == element.Layer).First().IsLocked)
                    continue;
                if (this.docRt.Document.Layers.Where(x => x.Name == element.Layer).First().IsOff)
                    continue;
                if (this.docRt.Document.Layers.Where(x => x.Name == element.Layer).First().IsFrozen)
                    continue;
                //暂时屏蔽轴网的夹点
                if (element is LcAxisCircle || element is LcAxisGrid || element is LcAxisLine)
                    continue;
                var grips = GetControlGrips(element);
                if (grips == null)
                    continue;
                ElementGrips.AddRange(grips);
            }
        }

        public void ClearElementGrips(List<LcElement> elements)
        {
            foreach (LcElement element in elements)
            {
                for (var i = ElementGrips.Count - 1; i >= 0; i--)
                {
                    if (ElementGrips[i].Element == element)
                    {
                        ElementGrips.RemoveAt(i);
                    }
                }
            }
        }
        /// <summary>
        /// 取消控制点
        /// </summary>
        public void ClearElementGrips()
        {
            ElementGrips.Clear();
        }


        public ControlGrip HitSelectGrip(Vector2 hitPoint, double selectSize)
        {
            SelectedGrip = null;
            for (var i = ElementGrips.Count - 1; i >= 0; i--)
            {
                var grip = ElementGrips[i];
                var testBox = new Box2(new Vector2(hitPoint.X - selectSize, hitPoint.Y - selectSize), selectSize * 2, selectSize * 2);
                var selected = grip.IntersectWithBox(testBox);
                if (selected)
                {
                    grip.IsSelected = true;
                    SelectedGrip = grip;
                    return grip;
                }
            }
            return null;
        }
        public ControlGrip HoverSelectGrip(Vector2 hitPoint, double selectSize)
        {
            HoveredGrip = null;
            for (var i = ElementGrips.Count - 1; i >= 0; i--)
            {
                var grip = ElementGrips[i];
                var testBox = new Box2(new Vector2(hitPoint.X - selectSize, hitPoint.Y - selectSize), selectSize * 2, selectSize * 2);
                var hovered = grip.IntersectWithBox(testBox);
                if (hovered)
                {
                    grip.IsHovered = true;
                    HoveredGrip = grip;
                    return grip;
                }
            }
            return null;
        }



        public void HoverUnselectGrip()
        {
            if (HoveredGrip != null)
            {

                HoveredGrip.IsHovered = false;
                HoveredGrip = null;
            }
        }

        public Action<SKCanvas> DrawDraggingGrip;

        public void DraggingGrip(Vector2 pw)
        {
            var ele = SelectedGrip.Element;
            SetDragGrip(SelectedGrip.Name, pw, false);
        }
        public void DraggingGripEnd(Vector2 pw)
        {
            var ele = SelectedGrip.Element;
            (ele.RtAction as ElementAction).SetDragGrip(ele, SelectedGrip.Name, pw, true);
            ele.ResetBoundingBox();
            //SelectsChanged?.Invoke(this, EventArgs.Empty);
            DrawDraggingGrip = null;
            ClearElementGrips(new List<LcElement> { ele });
            ResetElementGrips(new List<LcElement> { ele });

        }

        public ControlGrip[] GetControlGrips(LcElement element)
        {
            var action = element.RtAction as ElementAction;
            if (action == null)
                return new ControlGrip[0];
            ControlGrip[] grips = action.SetViewport(this).GetControlGrips(element);
            return grips;
        }

        public void SetDragGrip(string gripName, Vector2 position, bool isEnd)
        {
            var element = this.SelectedGrip.Element;
            var actionHandler = (element.RtAction as ElementAction);
            actionHandler.SetDragGrip(element, gripName, position, isEnd);
        }

        #endregion

        /// <summary>
        /// 平移可视范围
        /// </summary>
        public void PanViewScope()
        {
            var vp = this.Viewport;
            var dc_pressed = this.ScrToDcs.MultiplyPoint(this.PointerPressedPosition.ToVector2d());
            var dc_moved = this.ScrToDcs.MultiplyPoint(this.PointerMovedPosition.ToVector2d());
            var scrDx = dc_moved.X - dc_pressed.X;
            var scrDy = dc_moved.Y - dc_pressed.Y;
            if (scrDx == 0 && scrDy == 0) return;
            vp.Center = this.PanCenter + new Vector2(scrDx, scrDy);
            ResetCoordMatrix();
        }
        /// <summary>
        /// 缩放可视范围
        /// </summary>
        /// <param name="deltaY"></param>
        public void ZoomWheel(double deltaY)
        {
            var vport = this.Viewport;
            if (deltaY < 0)//zoom out 缩小
            {

                GridRatio *= (float)ZoomRatio;
                vport.Scale *= ZoomRatio;
            }
            else //zoom in 放大
            {

                GridRatio /= (float)ZoomRatio;
                vport.Scale /= ZoomRatio;
            }

            if (Math.Round(GridRatio, 6) < 1)
            {
                GridRatio = 5;
            }
            if (Math.Round(GridRatio, 6) > 5)
            {
                GridRatio = 1;
            }

            var zoom = (deltaY > 0) ? (1 / ZoomRatio) : ZoomRatio;
            var wheelp = ScrToWcs.MultiplyPoint(this.PointerWheelPosition.ToVector2d());
            var scaleMatrix = Matrix3.GetScale(zoom, wheelp);//围绕当前点的世界坐标缩放矩阵
            var org = scaleMatrix.MultiplyPoint(new Vector2());//缩放原点
            vport.Center = WcsToDcs.MultiplyPoint(org);//将原点映射的设备坐标空间
            this.ResetCoordMatrix();
        }
        private bool PopupContextMenu()
        {
            var dx = this.PointerReleasedPosition.X - this.PointerPressedPosition.X;
            var dy = this.PointerReleasedPosition.Y - this.PointerPressedPosition.Y;
            if (Math.Abs(dx) < 2 && Math.Abs(dy) < 2)
            {
                Control.PopupContextMenu(() =>
                {
                    SetStatus(storeStatus);//右键菜单关闭后立即恢复状态
                });
                return true;
            }
            return false;
        }



        internal void PasteDone()
        {
            var vportRt = this;
            var pointerPos = vportRt.PointerPressedPosition.ToVector2d();
            var wp = vportRt.ConvertScrToWcs(pointerPos);
            DocumentManager.CurrentRecorder.BeginAction("PASTE");
            foreach (var element in this.docRt.Action.PastingElements)
            {
                //element.Initilize(this.docRt.Document);
                //if (element is LcBlockRef)
                //{
                //    var blockRef = element as LcBlockRef;
                //    var blk = this.docRt.Document.Blocks[blockRef.BlockId];
                //    blockRef.Block = blk;
                //}

                //  var copyEle = element.Clone();
                //copyEle.Initilize(this.docRt.Document);//来自剪切板的元素没有Document上下文，需初始化
                element.Translate(wp.X, wp.Y);
                this.ActiveElementSet.InsertElement(element);
            }
            DocumentManager.CurrentRecorder.EndAction();
        }


        internal void CommandExecute(LcCommand command)
        {
            //if (command.Name.ToUpper() == "OPENUCS")
            //{
            //    this.Viewport.Ucs.Set(new Vector2d(100, 100), new Vector2d(1, 1).Normalized, new Vector2d(-1, 1).Normalized);
            //}
            //else
            if (command.Name.ToUpper() == "WCS")
            {
                this.Viewport.Ucs.SetIdentity();
            }
            else
            if (command.Name.ToUpper() == "PLAN")
            {
                this.Viewport.Ucs.IsPlan = true;
            }
            else if (command.Name.ToUpper() == "NOPLAN")
            {
                this.Viewport.Ucs.IsPlan = false;
            }
            ResetCoordMatrix();
        }


        public Vector2 ConvertScrToDcs(Vector2 p) { return ScrToDcs.MultiplyPoint(p); }
        public Vector2 ConvertDcsToScr(Vector2 p) { return DcsToScr.MultiplyPoint(p); }
        public Vector2 ConvertDcsToWcs(Vector2 p) { return DcsToWcs.MultiplyPoint(p); }
        public Vector2 ConvertWcsToDcs(Vector2 p) { return WcsToDcs.MultiplyPoint(p); }
        public Vector2 ConvertWcsToScr(Vector2 p) { return WcsToScr.MultiplyPoint(p); }
        public Vector2 ConvertScrToWcs(Vector2 p) { return ScrToWcs.MultiplyPoint(p); }
        public Vector2 ConvertUcsToWcs(Vector2 p) { return UcsToWcs.MultiplyPoint(p); }
        public Vector2 ConvertWcsToUcs(Vector2 p) { return WcsToUcs.MultiplyPoint(p); }
        public Vector2 ConvertUcsToScr(Vector2 p) { return UcsToScr.MultiplyPoint(p); }
        public Vector2 ConvertScrToUcs(Vector2 p) { return ScrToUcs.MultiplyPoint(p); }
        public double ConvertWcsToScr(double length)
        {
            return length * this.Viewport.Scale;
        }
        public double ConvertScrToWcs(double length)
        {
            return length / this.Viewport.Scale;
        }
        public ElementAction CurrentAction { get; set; }
        public void CancelCurrentAction()
        {
            if (CurrentAction != null)
            {
                CurrentAction.Cancel();
            }

            if (CheckStatus(ViewportStatus.DragSelection))
            {
                ClearStatus();
                this.docRt.Action.SetSelectsToDragging(false);
            }
            if (CheckStatus(ViewportStatus.DragGrip))
            {
                ClearStatus();
            }
            else
            {
                this.docRt.Action.ClearSelects();
            }
        }

        public void SetCreateDrawer(ICreateDrawer drawer)
        {
            if (drawer == null)
            {
                this.IsCreateDrawing = false;
                this.CreateDrawer = null;
            }
            else
            {
                this.IsCreateDrawing = true;
                this.CreateDrawer = drawer;
            }
        }
        public void SetTransformDrawer(ITransformDrawer drawer)
        {
            if (drawer == null)
            {
                this.IsTransformDrawing = false;
                this.transformDrawer = null;
            }
            else
            {
                this.IsTransformDrawing = true;
                this.transformDrawer = drawer;
            }
        }

        public void StartRefEditing()
        {
            this.ActiveElementSet = this.RefEditingObject;
            this.DeactiveElementSet = this.docRt.Document.ModelSpace;
            this.IsRefEditing = true;
        }
        public void CloseRefEditing()
        {
            this.ActiveElementSet = this.docRt.Document.ModelSpace;
            this.RefEditingObject?.SyncElements();
            this.RefEditingObject?.Dispose();
            this.RefEditingObject = null;
            this.DeactiveElementSet = null;
            this.IsRefEditing = false;

        }
        public void StartSectionEditing()
        {
            this.ActiveElementSet = this.SectionEditingObject;
            this.DeactiveElementSet = null;
         }
        public void CloseSectionEditing()
        {
            this.ActiveElementSet = this.docRt.Document.ModelSpace;
            this.SectionEditingObject ?.SyncElements();
            this.SectionEditingObject?.Dispose();
            this.SectionEditingObject = null;
            this.DeactiveElementSet = null;
        }
        public Polygon2d GetBoundsPolygon()
        {
            LcViewport vp = this.Viewport;
            Vector2 p0 = this.ScrToWcs.MultiplyPoint(Vector2.Zero);
            Vector2 p1 = this.ScrToWcs.MultiplyPoint(new Vector2(0, vp.Height));
            Vector2 p2 = this.ScrToWcs.MultiplyPoint(new Vector2(vp.Width, vp.Height));
            Vector2 p3 = this.ScrToWcs.MultiplyPoint(new Vector2(vp.Width, 0));
            return new Polygon2d { Points = new Vector2[] { p0, p1, p2, p3 } };
        }

        internal List<LcElement> GetElementsInBounds(CancellationTokenSource cts = null)
        {
            var bpoly = this.GetBoundsPolygon();
            var bbox = bpoly.BoundingBox;
            var elements = new List<LcElement>();
            foreach (var ele in this.ActiveElementSet.Elements)
            {
                if (cts != null && cts.IsCancellationRequested) return elements;
                if (ele.BoundingBox == null)
                {
                    continue;
                }
                if (ele.BoundingBox.IntersectsBox(bbox))
                {
                    elements.Add(ele);
                }
            }
            return elements;
        }

        public double GetSnapMaxDistance()
        {
            return this.ConvertScrToWcs(SnapSettings.MaxDistance);
        }

        public void DrawArc(Arc2d arc2D, Matrix3 matrix, SKCanvas canvas, SKPaint pen)
        {
            var cp = arc2D.Center;
            var radius = arc2D.Radius;
            var startAngle = arc2D.StartAngle;
            var endAngle = arc2D.EndAngle;
            ArcCurve arcCurve = new ArcCurve(cp.X, cp.Y, radius, startAngle, endAngle, arc2D.IsClockwise);
            var divCount = (int)Math.Ceiling(radius * this.Viewport.Scale);
            if (divCount < 5)
                divCount = 5;
            if(divCount>128)
                divCount=128;
            var points = arcCurve.getPoints(divCount).Select(p => this.ConvertWcsToScr(matrix.MultiplyPoint(new Vector2(p.X, p.Y))).ToSKPoint()).ToArray();
            canvas.DrawPoints(SKPointMode.Polygon, points, pen);
        }
        public void DrawCircle(Circle2d circle2D, Matrix3 matrix, SKCanvas canvas, SKPaint pen)
        {
            ArcCurve arcCurve = new ArcCurve(circle2D.Center.X, circle2D.Center.Y, circle2D.Radius, 0, Utils.TwoPI, false);
            var radius = circle2D.Radius;
            var divCount = (int)Math.Ceiling(radius * this.Viewport.Scale);
            if (divCount < 5)
                divCount = 5;
            var points = arcCurve.getPoints(divCount).Select(p => this.ConvertWcsToScr(matrix.MultiplyPoint(new Vector2(p.X, p.Y))).ToSKPoint()).ToArray();
            canvas.DrawPoints(SKPointMode.Polygon, points, pen);
        }
        public void DrawEllipse(Ellipse2d ellipse2D, Matrix3 matrix, SKCanvas canvas, SKPaint pen)
        {
            var cp = ellipse2D.Center;
            EllipseCurve ellipseCurve = new EllipseCurve(cp.X, cp.Y, ellipse2D.RadiusX, ellipse2D.RadiusY, ellipse2D.StartAngle, ellipse2D.EndAngle, ellipse2D.IsClockwise, ellipse2D.Rotation);
            var radius = Math.Max(ellipse2D.RadiusX, ellipse2D.RadiusY);
            var divCount = (int)Math.Ceiling(radius * this.Viewport.Scale);
            if (divCount < 5)
                divCount = 5;
            var points = ellipseCurve.getPoints(divCount).Select(p => this.ConvertWcsToScr(matrix.MultiplyPoint(new Vector2(p.X, p.Y))).ToSKPoint()).ToArray();
            canvas.DrawPoints(SKPointMode.Polygon, points, pen);
        }

        public void DrawText(Vector2 alipoint, Vector2 textstart, double height, double rotate, string text, double tilt, string typeface, double widthfactor, string alignment, Matrix3 matrix, SKCanvas canvas, SKPaint pen)
        {
            var pathpoint = new Vector2(0, 0).ToSKPoint();
            #region 通过角度计算向量
            var newendpoint = Vector2.Rotate(new Vector2(textstart.X + 100, textstart.Y), textstart, rotate);
            var xlpoint = new Vector2(newendpoint.X - textstart.X, newendpoint.Y - textstart.Y);
            #endregion

            #region 根据文字宽度 向量 计算path的结束点
            //宽度公式
            //文字  英文字母  数字 特殊字符的长度不一样
            string chtext = "";
            string nochtext = "";
            string engtext = "";
            string tstext = "";

            Regex regex = new Regex(@"^[\u4E00-\u9FA5]{0,}$");

            for (int i = 0; i < text.Length; i++)
            {
                if (regex.IsMatch(text[i].ToString()))
                {
                    //中文
                    chtext = chtext + text[i].ToString();
                }
                else
                {
                    //不是中文
                    nochtext = nochtext + text[i].ToString();
                }
            }
            //取出字符串中所有的数字 ,字母      
            engtext = Regex.Replace(text, @"[^A-Za-z0-9]+", "", RegexOptions.IgnoreCase);

            //处理特殊字符（特殊字符）
            tstext = Regex.Replace(nochtext, @"[A-Za-z0-9]", "", RegexOptions.IgnoreCase);

            //因为字母 数字 的长度只能给一半
            double dis = 0;
            //特殊字符按中文长度算
            if (tstext != "" && tstext.Length > 0)
            {
                dis += height * widthfactor * tstext.Length * 1;
            }
            if (chtext != "" && chtext.Length > 0)
            {
                dis += height * widthfactor * chtext.Length * 1;
            }
            if (engtext != "" && engtext.Length > 0)
            {
                dis += Math.Round((height * widthfactor * engtext.Length * 1) / 2);
            }




            #endregion

            #region
            var painttext = new SKPaint();
            var fontManager1 = SKFontManager.Default;
            var emojiTypeface1 = fontManager1.MatchCharacter('时');
            var index = SKFontManager.Default.FontFamilies.ToList().IndexOf(typeface);
            // 创建宋体字形
            var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
            painttext.TextSize = (float)(this.Viewport.Scale * height);
            //painttext.TextAlign =SKTextAlign.Center;
            painttext.IsAntialias = false;
            painttext.Color = new SKColor(0x42, 0x81, 0xA4);
            painttext.IsStroke = false;
            painttext.Typeface = songtiTypeface;
            //倾斜度
            painttext.TextSkewX = (float)tilt;

            //宽度因子
            painttext.TextScaleX = (float)widthfactor;


            Vector2 lidisptpos = new Vector2();
            SKPoint newend;
            //判断是哪种对齐方式
            if (alignment == "右对齐")
            {

                //右对齐就是  起点变为结束点  计算新的起点
                lidisptpos = alipoint - (new Vector2(xlpoint.X * dis, xlpoint.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(xlpoint.X, 2.0) + Math.Pow(xlpoint.Y, 2.0))));

                var mnewstart = matrix.MultiplyPoint(lidisptpos.Clone());
                var newstart = this.ConvertWcsToScr(mnewstart).ToSKPoint();




                //新的文字起点
                textstart = lidisptpos;

            }
            else if (alignment == "左对齐")
            {
                textstart = alipoint;
            }
            Vector2 xlend = textstart + (new Vector2(xlpoint.X * dis, xlpoint.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(xlpoint.X, 2.0) + Math.Pow(xlpoint.Y, 2.0))));

            var mstart = matrix.MultiplyPoint(textstart);
            var start = this.ConvertWcsToScr(mstart).ToSKPoint();
            var mend = matrix.MultiplyPoint(xlend);
            var end = this.ConvertWcsToScr(mend).ToSKPoint();




            var skpath = new SKPath();
            skpath.MoveTo(start);
            //skpath.LineTo((float)start.X, (float)start.Y);
            skpath.LineTo((float)end.X, (float)end.Y);


            SKFont sKFont = new SKFont();
            sKFont.Typeface = songtiTypeface;
            sKFont.Size = (float)(this.Viewport.Scale * height);

            //倾斜度
            sKFont.SkewX = (float)tilt;

            //宽度因子
            sKFont.ScaleX = (float)widthfactor;

            canvas.DrawTextOnPath(text, skpath, pathpoint, false, sKFont, painttext);




            #endregion


        }
    }
}
